/**
 * Copyright (C) 2011  E-Robot
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 * @brief Map.cpp
 *
 * @date 21 nov. 2010
 * @author elca
 * @version 0.1
 */

#include "Map.h"
#include "../def.h"
#include <qdebug.h>
#include <math.h>
#include <QKeyEvent>
#include <QTime>
#define BORDER 10

Map::Map(int _nbrCellWidth, int _nbrCellHeight, int _size, int _resolution)
{
	useGRO = false;

	this->size = _size;
	this->resolution = _resolution;
	this->width = _nbrCellWidth*size*resolution;
	this->height = _nbrCellHeight*size*resolution;;

	//Scene rect
	xScene = -(width/2)%size-(width/2)-size;
	yScene = -(height/2)%size-(height/2)-size;
	widthScene = 2*((width/2)%size+(width/2)+size);
	heightScene = 2*((height/2)%size+(height/2)+size);

	qDebug()<< "Width:"<<width<<" Height:"<<height<< " size:"<<size<< " reso:"<<  resolution;
	qDebug()<< "xSe:"<<xScene<<" ySe:"<<yScene<<" wiSe:"<<widthScene<<" heiSce:"<<heightScene;

	QRect sceneRect(
			xScene-BORDER,
			yScene-BORDER,
			widthScene+2*BORDER,
			heightScene+2*BORDER);

	setSceneRect(sceneRect);

	//Nombre de cellules
	int nbCellHeight = heightScene/size;
	int nbCellWidth = widthScene/size;
	qDebug()<< "nbrCellWidth:"<<_nbrCellWidth<<" nbrCellHeight:"<<_nbrCellHeight<<" nbCellWidth:"<<nbCellWidth<<" nbCellHeight:"<<nbCellHeight;

	//Création des cellules
	int xI,yI;
	for(int i=0;i<nbCellHeight;i++){
		cells.append(QVector<Cell*>());
		for(int j=0;j<nbCellWidth;j++){
			xI= xScene +j*size;
			yI= yScene +i*size;

			cells[i].append(new Cell(xI,yI,size,size,this));
			connect(this,SIGNAL(changeMask(int)),cells[i].at(j),SLOT(changeMask(int)));
			connect(this,SIGNAL(resetMap()),cells[i].at(j),SLOT(resetCell()));

		}
	}


	//Millieu du tableau de cellules
	mY = cells.size()/2;
	mX = cells[0].size()/2;

	qDebug()<< "millieuX:"<<mX<<" millieuY:"<<mY;


	//Création d'axe au millieu de la grille
	QGraphicsLineItem* axeX = new QGraphicsLineItem(xScene,0,xScene+widthScene,0,NULL,this);
	axeX->setPen(QPen(QBrush(Qt::black),2));
	QGraphicsLineItem* axeY = new QGraphicsLineItem(0,yScene,0,yScene+heightScene,NULL,this);
	axeY->setPen(QPen(QBrush(Qt::black),2));

	axe.append(axeX);
	axe.append(axeY);


	coefHIMM[0][0] = 0.5;coefHIMM[0][1] = 0.5;coefHIMM[0][2] = 0.5;
	coefHIMM[1][0] = 0.5;coefHIMM[1][1] =   1;coefHIMM[1][2] = 0.5;
	coefHIMM[2][0] = 0.5;coefHIMM[2][1] = 0.5;coefHIMM[2][2] = 0.5;
	//Position to case cellule
//	double p1,p2,p3,p4;
//	p1 = fmod(xp,res);
//	if(xp <0 && p1 !=0){
//		p1 = res + p1;
//	}
//	p2 = xp - p1;
//	p3 = p2/res;
//	p4 = m+p3;
//
//	qDebug()<< p1;
//	qDebug()<< p2;
//	qDebug()<< p3;
//	qDebug()<< p4;


}

int Map::getX(double _x){
	return (int) (mX + _x*resolution);
}

int Map::getY(double _y){
	return (int) (mY - _y*resolution);
}

void Map::updateCell(QLineF _line){
	//

//	static QTime timer;

//	timer.restart();

	static double l;
	static double tmpVal;
	static int max;

	static QGraphicsLineItem litem;
	static int size_res = size*resolution;

	l = _line.length();

	//Position dans tableau de x et y début,fin
	static int  yS, yE,xS,xE;
	yS = getY(_line.p1().y());
	yE = getY(_line.p2().y());
	xS = getX(_line.p1().x());
	xE = getX(_line.p2().x());

	//Item de test pour collision
	//items.at(nbsonar)->setLine(_line.p1().x()*size/resolution,-1*_line.p1().y()*size/resolution,_line.p2().x()*size/resolution,-1*_line.p2().y()*size/resolution);
	litem.setLine(_line.p1().x()*size_res,-1*_line.p1().y()*size_res,_line.p2().x()*size_res,-1*_line.p2().y()*size_res);
//	qDebug()<<_line;
//	qDebug()<< _line.p1().x()*size_res<<" "<<-1*_line.p1().y()*size_res<<" "<<_line.p2().x()*size_res<<" "<<-1*_line.p2().y()*size_res;
//	qDebug()<< "yS:"<<yS<< "yE:"<<yE<< "xS:"<<xS<< "xE:"<<xE;
	//Parcours rectangle formé par la ligne
	for(int j = yS;(yS<=yE)?j<=yE:j>=yE;(yS<=yE)?j++:j--){
		for(int i = xS;(xS<=xE)?i<=xE:i>=xE;(xS<=xE)?i++:i--){

			//S'il y a collision faudra incrémenter la cellule
//			if(items.at(nbsonar)->collidesWithItem(cells[j].at(i))){
			if(litem.collidesWithItem(cells[j].at(i))){
//				qDebug()<<j<< "____ "<<i;
				mut.lock();
				//Incrément de 3 ssi distance < max et on est en bout de ligne
				if(!(fabs(l-MAX_DISTANCE_SONAR)<0.0001) && i==xE && j == yE){
					cells[j].at(i)->increment(3);
					//Use Growth rate operator
//					if(useGRO){
//						tmpVal=0;
//						max = 0;
//						for(int k=0;k<3;k++){
//							for(int l=0;l<3;l++){
//								if((j+k-1)> 0 && (i+l-1)>0 && (j+k-1)< cells.size() && (i+l-1)<cells[0].size()){
//
//									if(cells[j+k-1].at(i+l-1)->value()>max){
//										max = cells[j+k-1].at(i+l-1)->value();
//									}
//									tmpVal += cells[j+k-1].at(i+l-1)->value()*coefHIMM[k][l];
//								}
//							}
//						}
//
//						if(tmpVal< max){
//							cells[j].at(i)->setValue(tmpVal);
//						}else{
//							cells[j].at(i)->setValue(max);
//						}
//					}
				}else{
					cells[j].at(i)->increment(-1);
				}
				mut.unlock();

			}

		}
	}
//	nbsonar= (nbsonar+1)%15;

	update(xScene,yScene,widthScene,heightScene);
//	qDebug()<<"UpdageSonar: "<<timer.elapsed();
	//

}

//void Map::updateCell(QLineF _line){
//	mut.lock();
//		QPolygonF poly;
//
//
//		double l = _line.length();
//		_line.setLine(_line.p1().x()*size/resolution,-1*_line.p1().y()*size/resolution,_line.p2().x()*size/resolution,-1*_line.p2().y()*size/resolution);
//
//		poly.append(_line.p1());
//		poly.append(_line.p2());
//		QList<QGraphicsItem*> list;
//
//		qDebug()<< poly<< "l="<<l;
////		QPainterPath path;
////		path.addPolygon(poly);
////
////
////		scene->setSelectionArea(path,Qt::IntersectsItemShape);
////		list = scene->selectedItems();
//
//
//		list = items(poly,Qt::IntersectsItemShape);
////		list =line->collidingItems(Qt::IntersectsItemShape);
//		bool disOK = (fabs(l-MAX_DISTANCE_SONAR)<0.0001);
//		qDebug()<< list.size()<<" bool="<<!disOK<<" ____"<<fabs(l-MAX_DISTANCE_SONAR)<<"_____________-";
//
//		bool last = false;
//		Cell *tmp;
//		QPointF ptLast = poly.last();
//
//		Cell *lastCell = qgraphicsitem_cast<Cell*>(itemAt(ptLast));
//		for(int i =0;i<list.size();i++){
//			tmp = qgraphicsitem_cast<Cell*>(list.at(i));
//			if(tmp != lastCell){
//				tmp->increment(-1);
//			}else if (!disOK){
//				last = true;
//				tmp->increment(3);
//			}else{
//				last = true;
//				tmp->increment(-1);
//
//			}
//		}
//		if(!last && !disOK) lastCell->increment(3);
//		else if (!last) lastCell->increment(-1);
//
//		QRectF up(_line.p1(),_line.p2());
//		up = up.normalized();
//		up.setX(up.x()-2*size);
//		up.setY(up.y()-2*size);
//		up.setWidth(up.width()+4*size);
//		up.setHeight(up.height()+4*size);
//
//		update(up);
//		mut.unlock();
//}

void Map::keyPressEvent ( QKeyEvent * event ){
	if(event->key()==Qt::Key_1 || event->key()==Qt::Key_2|| event->key()==Qt::Key_4|| event->key()==Qt::Key_8){
		Q_EMIT(changeMask(event->key()-48));
	}

	if(event->key()==Qt::Key_G){
		useGRO = !useGRO;
		qDebug()<< "Is GRO used: "<<useGRO;
	}

	if(event->key()==Qt::Key_Right){
		Q_EMIT(changeAlgo());
	}

	if(event->key()==Qt::Key_R){
		Q_EMIT(resetMap());
	}
	if(event->key()==Qt::Key_A){
		for(int i=0; i< axe.size();i++){
			axe.at(i)->setVisible(!axe.at(i)->isVisible());
		}
	}
}


Map::~Map()
{
	// TODO Auto-generated destructor stub
}
